﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Data.Common;
using BizTalk.ESB.Extensions.SSO.BizTalk;
using Microsoft.XLANGs.BaseTypes;
using Microsoft.XLANGs.Core;
using System.Collections;

namespace BizTalk.ESB.Extensions.Helpers
{
    [Serializable]
    public enum MapSourceType
    {
        Original,
        ServiceRequest,
        ServiceResponse,
        Merge,
        None
    }

    [Serializable]
    public enum ServiceType
    {
        Orchestration,
        Messaging
    }

    [Serializable]
    public enum ValidationType
    {
        None,
        BRE,
        XSD
    }

    public class ItineraryHelper
    {
        public static ItineraryWrapper parseResolverString(string resolverString, Boolean DebugFlag)
        {
            ItineraryWrapper iw = new ItineraryWrapper();
            System.Diagnostics.Trace.WriteLineIf(DebugFlag, "resolverString: = " + resolverString);
            string[] keyValue = resolverString.Split('@');
            Dictionary<string, string> dictionary = new Dictionary<string, string>();

            // Save all key-value pairs in the dictionary
            foreach (string str in keyValue)
            {
                System.Diagnostics.Trace.WriteLineIf(DebugFlag, "***** DEBUG ***** -- Current Key:  " + str);

                if (String.IsNullOrEmpty(str) == false)
                {
                    try
                    {
                        string key = str.Substring(0, str.IndexOf('='));
                        string value = str.Substring(str.IndexOf('=') + 2).TrimEnd('\"');
                        System.Diagnostics.Trace.WriteLine("Key: " + key + " value: " + value);
                        dictionary.Add(key, value);
                        iw.SetCustomProperty(key, value);
                    }
                    catch (Exception e)
                    {
                        System.Diagnostics.Trace.WriteLineIf(DebugFlag, "***** DEBUG ***** -- " + e.ToString());
                    }
                }
            }

            // Capture Service Name, Service Type and WCF Action if they exist
            try
            {
                if (dictionary.ContainsKey("serviceName"))
                {
                    iw.serviceName = dictionary["serviceName"];
                }
                if (dictionary.ContainsKey("serviceType"))
                {
                    iw.serviceType = dictionary["serviceType"];
                }
                if (dictionary.ContainsKey("wcfAction"))
                {
                    iw.wcfAction = dictionary["wcfAction"];
                }
            }
            catch (Exception e)
            {
                System.Diagnostics.Trace.WriteLineIf(DebugFlag, "***** DEBUG ***** -- " + e.ToString());
            }
            return iw;
        }

        public static MapSourceType ConvertToMapSourceType(String MapOption)
        {
            if (String.IsNullOrEmpty(MapOption) == false)
            {
                return (MapSourceType)Enum.Parse(
                    typeof(MapSourceType), MapOption, true);
            }
            else
            {
                throw new ArgumentNullException("MapOption parameter cannot be null or empty");
            }
        }

        public static ValidationType ConvertToValidationType(String ValidateOption)
        {
            if (String.IsNullOrEmpty(ValidateOption) == false)
            {
                return (ValidationType)Enum.Parse(
                    typeof(ValidationType), ValidateOption, true);
            }
            else
            {
                throw new ArgumentNullException("ValidateOption parameter cannot be null or empty");
            }
        }

        public static HybridDictionary GetSsoConfiguration(string ApplicationName)
        {
            return SsoConfigWrapper.GetConfigSet(ApplicationName);
        }

        public static XLANGMessage MergeXlangContext(XLANGMessage OriginalMessage, XLANGMessage ServiceResponseMessage, bool DebugFlag)
        {
            var output = string.Empty;
            if (OriginalMessage == null || ServiceResponseMessage == null)
            {
                throw new ArgumentNullException("Orchestration Message", "Message cannot be null");
            }
            else
            {
                var contextToCopy = GetXlangMessageContext(OriginalMessage, DebugFlag);
                foreach (DictionaryEntry prop in contextToCopy)
                {
                    Type propType = null;
                    if (!string.IsNullOrEmpty(GetContextPropertyValue(ServiceResponseMessage, prop.Key.ToString(), out propType)))
                    {
                        ServiceResponseMessage.SetPropertyValue(propType, prop.Value);
                    }
                }
            }
            return ServiceResponseMessage;
        }

        private static Hashtable GetXlangMessageContext(XLANGMessage message, bool DebugFlag)
        {
            Hashtable result = null;

            try
            {
                foreach (Segment segment in Service.RootService._segments)
                {
                    var fields = Context.FindFields(typeof(XLANGMessage), segment.ExceptionContext);

                    foreach (DictionaryEntry field in fields)
                    {
                        XMessage msg = (field.Value as XMessage);

                        if (msg != null && String.Compare(msg.Name, message.Name) == 0)
                        {
                            result = msg.GetContextProperties();
                            break;
                        }
                    }

                    if (result != null)
                        break;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLineIf(DebugFlag,
                    String.Format("Error while collecting Context Collection from XLANGMessage. Description: {0}, Stack Trace: {1}", ex.Message, ex.StackTrace));
            }

            return result;
        }

        private static string GetContextPropertyValue(XLANGMessage Message, string keyValue, out Type PropertyType)
        {
            PropertyType = null;
            var output = string.Empty;
            if (!string.IsNullOrEmpty(keyValue))
            {
                var splitLocation = keyValue.LastIndexOf(@"/");
                var propNamespace = keyValue.Substring(0, splitLocation);
                var propName = keyValue.Substring(splitLocation + 1);

                XmlQName prop = new XmlQName(propName, propNamespace);
                PropertyType = prop.GetType();
                output = Convert.ToString(Message.GetPropertyValue(prop.GetType()));
            }
            return output;
        }

    }
}

[Serializable]
public class ItineraryWrapper
{
    public string serviceName = "";
    public string serviceType = "";
    public string wcfAction = "";

    private System.Collections.Specialized.HybridDictionary CustomProperties;

    public Object GetCustomProperty(String PropertyName)
    {
        if (this.CustomProperties != null)
        {
            if (this.CustomProperties.Contains(PropertyName))
            {
                return this.CustomProperties[PropertyName];
            }
            else
            {
                return String.Empty;
            }
        }
        else
        {
            return null;
        }
    }

    public void SetCustomProperty(String PropertyName, Object PropertyValue)
    {
        if (this.CustomProperties == null)
        {
            this.CustomProperties = new System.Collections.Specialized.HybridDictionary();
        }
        this.CustomProperties.Add(PropertyName, PropertyValue);
    }
}

